/*
 * facesdkwrapper.cpp
 *
 *  Created on: 2016年3月25日
 *      Author: guyadong
 */

#include "facesdkwrapper.h"
#include "FR_IV_STD.h"
namespace gdface {
/* 将facesdk的初始化和资源释放封装成类 */
class facesdk_resource{
private:
	bool _init(){
		// Visable image recognize Initialize
		int ret=FD_Init();
		if(ret == 0)
		{
			return false;
		}
		ret=FR_Initial();
		if(ret == 0)
		{
			return false;
		}
		Descision_Initialize_V(0, 0);
		return true;
	}
	void init(){
		static std::once_flag oc;
		std::call_once(oc, [&] {throw_if_msg(!_init(),"fail to initialize facesdk");});
	}
	void _release(){
		FD_Uninit();
		FR_FreeMemory();
		Descision_ClearMem_V();
	}
	void release(){
		static std::once_flag oc;
		std::call_once(oc, [&] {_release();});
	}
	facesdk_resource(){
		init();
	}
	const static facesdk_resource instance;
public:
	~facesdk_resource(){
		release();
	}
};
const facesdk_resource facesdk_resource::instance;
face_info_type facesdk_wrapper::detect_face(const uint8_t* gray_img_ptr, uint16_t width, uint16_t height,
		uint16_t row_stride, bool eye, double fscale, const FSize& min, const FSize& max) const {
	throw_if(nullptr == gray_img_ptr)
	auto img = gray_img_ptr;
	std::vector<uint8_t> img0;
	if (row_stride != width && 0 != row_stride) {
		img0 = std::vector<uint8_t>(width * height);
		auto src_ptr = gray_img_ptr;
		for (auto dst_ptr = img0.data(), end = img0.data() + img0.size();
				dst_ptr < end;
				src_ptr += row_stride, dst_ptr += width)
			memcpy(const_cast<uint8_t*>(dst_ptr), const_cast<uint8_t*>(src_ptr), width);
		img = img0.data();
	}
	std::vector<FacePos> facepos(MAX_FACE_NUM);
	std::vector<EyeInfo> irispos(MAX_FACE_NUM);
	const FSize def_max_win{ (short int)std::min(width,height), (short int)std::min(width,height) };
	int face_num=0;
	auto res=FD_Face(img
		,width, height
		,&face_num, facepos.data()
		,eye ? irispos.data() : nullptr
		,fscale
		,min.width < DEFAULT_MIN_SIZE.width|| min.height < DEFAULT_MIN_SIZE.height ? &DEFAULT_MIN_SIZE : &min
		,max.width == DEFAULT_MAX_SIZE.width ? &def_max_win : &max);
	return std::make_pair(std::vector<FacePos>(facepos.data(), facepos.data() + face_num),
			eye ? std::vector<EyeInfo>(irispos.data(), irispos.data() + face_num) : std::vector<EyeInfo>());
}
face_info_type facesdk_wrapper::detect_face(const cimg_gray_type& gray_img, bool eye, double fscale,
		const FSize& min, const FSize& max) const {
	throw_if(1 != gray_img._spectrum)
	return detect_face(gray_img._data, uint16_t(gray_img.width()), uint16_t(gray_img.height()), 0, eye, fscale, min,
			max);
}

face_info_type facesdk_wrapper::detect_face(const image_matrix_param& gray_img, bool eye, double fscale,
		const FSize& min, const FSize& max) const {
	throw_if(JCS_GRAYSCALE != gray_img.color_space)
	auto row_stride = get_row_stride(gray_img);
	throw_if(gray_img.pixels.size() != row_stride * gray_img.height)
	return detect_face(gray_img.pixels.data(), uint16_t(gray_img.width), uint16_t(gray_img.height),
			uint16_t(row_stride), eye, fscale, min, max);
}

} /* namespace gdface */
